// Contains code copied from istanbul-reports (https://github.com/istanbuljs/istanbuljs/tree/main/packages/istanbul-reports).
// The link to the original license is in the VENDORED.md file in the parent directory.

var addSorting = (function () {
  "use strict";
  var cols,
    currentSort = {
      index: 0,
      desc: false,
    };

  // returns the summary table element
  function getTable() {
    return document.querySelector(".coverage-summary");
  }
  // returns the thead element of the summary table
  function getTableHeader() {
    return getTable().querySelector("thead tr");
  }
  // returns the tbody element of the summary table
  function getTableBody() {
    return getTable().querySelector("tbody");
  }
  // returns the th element for nth column
  function getNthColumn(n) {
    return getTableHeader().querySelectorAll("th")[n];
  }

  function onFilterInput() {
    const searchValue = document.getElementById("fileSearch").value;
    const rows = document.getElementsByTagName("tbody")[0].children;

    // Try to create a RegExp from the searchValue. If it fails (invalid regex),
    // it will be treated as a plain text search
    let searchRegex;
    try {
      searchRegex = new RegExp(searchValue, "i"); // 'i' for case-insensitive
    } catch (error) {
      searchRegex = null;
    }

    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      let isMatch = false;

      if (searchRegex) {
        // If a valid regex was created, use it for matching
        isMatch = searchRegex.test(row.textContent);
      } else {
        // Otherwise, fall back to the original plain text search
        isMatch = row.textContent
          .toLowerCase()
          .includes(searchValue.toLowerCase());
      }

      row.style.display = isMatch ? "" : "none";
    }
  }

  // loads the search box
  function addSearchBox() {
    var template = document.getElementById("filterTemplate");
    var templateClone = template.content.cloneNode(true);
    templateClone.getElementById("fileSearch").oninput = onFilterInput;
    template.parentElement.appendChild(templateClone);
  }

  // loads all columns
  function loadColumns() {
    var colNodes = getTableHeader().querySelectorAll("th"),
      colNode,
      cols = [],
      col,
      i;

    for (i = 0; i < colNodes.length; i += 1) {
      colNode = colNodes[i];
      col = {
        key: colNode.getAttribute("data-col"),
        sortable: !colNode.getAttribute("data-nosort"),
        type: colNode.getAttribute("data-type") || "string",
      };
      cols.push(col);
      if (col.sortable) {
        col.defaultDescSort = col.type === "number";
        colNode.innerHTML = colNode.innerHTML + '<span class="sorter"></span>';
      }
    }
    return cols;
  }
  // attaches a data attribute to every tr element with an object
  // of data values keyed by column name
  function loadRowData(tableRow) {
    var tableCols = tableRow.querySelectorAll("td"),
      colNode,
      col,
      data = {},
      i,
      val;
    for (i = 0; i < tableCols.length; i += 1) {
      colNode = tableCols[i];
      col = cols[i];
      val = colNode.getAttribute("data-value");
      if (col.type === "number") {
        val = Number(val);
      }
      data[col.key] = val;
    }
    return data;
  }
  // loads all row data
  function loadData() {
    var rows = getTableBody().querySelectorAll("tr"),
      i;

    for (i = 0; i < rows.length; i += 1) {
      rows[i].data = loadRowData(rows[i]);
    }
  }
  // sorts the table using the data for the ith column
  function sortByIndex(index, desc) {
    var key = cols[index].key,
      sorter = function (a, b) {
        a = a.data[key];
        b = b.data[key];
        return a < b ? -1 : a > b ? 1 : 0;
      },
      finalSorter = sorter,
      tableBody = document.querySelector(".coverage-summary tbody"),
      rowNodes = tableBody.querySelectorAll("tr"),
      rows = [],
      i;

    if (desc) {
      finalSorter = function (a, b) {
        return -1 * sorter(a, b);
      };
    }

    for (i = 0; i < rowNodes.length; i += 1) {
      rows.push(rowNodes[i]);
      tableBody.removeChild(rowNodes[i]);
    }

    rows.sort(finalSorter);

    for (i = 0; i < rows.length; i += 1) {
      tableBody.appendChild(rows[i]);
    }
  }
  // removes sort indicators for current column being sorted
  function removeSortIndicators() {
    var col = getNthColumn(currentSort.index),
      cls = col.className;

    cls = cls.replace(/ sorted$/, "").replace(/ sorted-desc$/, "");
    col.className = cls;
  }
  // adds sort indicators for current column being sorted
  function addSortIndicators() {
    getNthColumn(currentSort.index).className += currentSort.desc
      ? " sorted-desc"
      : " sorted";
  }
  // adds event listeners for all sorter widgets
  function enableUI() {
    var i,
      el,
      ithSorter = function ithSorter(i) {
        var col = cols[i];

        return function () {
          var desc = col.defaultDescSort;

          if (currentSort.index === i) {
            desc = !currentSort.desc;
          }
          sortByIndex(i, desc);
          removeSortIndicators();
          currentSort.index = i;
          currentSort.desc = desc;
          addSortIndicators();
        };
      };
    for (i = 0; i < cols.length; i += 1) {
      if (cols[i].sortable) {
        // add the click event handler on the th so users
        // dont have to click on those tiny arrows
        el = getNthColumn(i).querySelector(".sorter").parentElement;
        if (el.addEventListener) {
          el.addEventListener("click", ithSorter(i));
        } else {
          el.attachEvent("onclick", ithSorter(i));
        }
      }
    }
  }
  // adds sorting functionality to the UI
  return function () {
    if (!getTable()) {
      return;
    }
    cols = loadColumns();
    loadData();
    addSearchBox();
    addSortIndicators();
    enableUI();
  };
})();

window.addEventListener("load", addSorting);
